Security News
The Risks of Misguided Research in Supply Chain Security
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
value-enhancer
Advanced tools
A tiny library to enhance value with reactive wrapper.
npm add value-enhancer
The goal of this lib is to bring reactivity to values like MobX but without the implicit-cast magic. It is like RxJS but trimmed and simplified with the focus on value changes instead of async operations which resulted in much smaller codebase.
import { Val, combine, derive } from "value-enhancer";
const val = new Val(2);
console.log(val.value); // 2
val.setValue(3);
console.log(val.value); // 3
val.subscribe(value => console.log(`subscribe: ${value}`)); // subscribe: 3
val.reaction(value => console.log(`reaction: ${value}`)); // (nothing printed)
val.setValue(3); // nothing happened
val.setValue(4); // subscribe: 4, reaction: 4
const derived = derive(val, value => value * 3);
console.log(derived.value); // 12
derived.subscribe(value => console.log(`derived: ${value}`)); // derived: 12
const combined = combine([val, derived], ([val, derived]) => val + derived);
console.log(combined.value); // 16
combined.subscribe(value => console.log(`combined: ${value}`)); // combined: 16
val.setValue(5); // subscribe: 5, reaction: 5, derived: 15, combined: 20
setValue
may carry any type of extra info via meta
param.
val.subscribe((value, meta) => console.log(value, meta));
val.setValue(5, { source: "remote" });
Bind Vals value
, setValue
and itself to properties of an instance.
import type { ValEnhancedResult } from "value-enhancer";
import { Val, withValueEnhancer } from "value-enhancer";
type ValConfig = {
apple: Val<string>;
banana: Val<string>;
};
interface Obj extends ValEnhancedResult<ValConfig> {}
class Obj {
constructor() {
const apple$ = new Val("apple");
const banana$ = new Val("banana");
withValueEnhancer(this, {
apple: apple$,
banana: banana$,
});
}
}
const obj = new Obj()
results in:
obj.apple
, a getter that returns apple$.value
, setter same as apple$.setValue(value)
obj._apple$
, the apple$
obj.setApple(value)
, same as apple$.setValue(value)
obj.banana
, a getter that returns banana$.value
, setter same as banana$.setValue(value)
obj.setBanana(value)
, same as banana$.setValue(value)
obj._banana$
, the banana$
obj.onValChanged(key: "apple" | "banana", listener)
, equals to calling obj[`_${key}$`].reaction
Like withValueEnhancer
, withReadonlyValueEnhancer
binds ReadonlyVals/Vals to a instance but without setters
import type { ReadonlyValEnhancedResult } from "value-enhancer";
import { Val, withReadonlyValueEnhancer } from "value-enhancer";
type ReadonlyValConfig = {
apple: Val<string>;
isApple: ReadonlyVal<boolean>;
};
interface Obj extends ReadonlyValEnhancedResult<ReadonlyValConfig> {}
class Obj {
constructor() {
const apple$ = new Val("apple");
const isApple$ = derive(apple$, apple => apple === "apple");
withReadonlyValueEnhancer(this, {
apple: apple$,
isApple: isApple$,
});
}
}
const obj = new Obj()
results in:
obj.apple
, a getter that returns apple$.value
obj._apple$
, the apple$
obj.isApple
, a getter that returns isApple$.value
obj._isApple$
, the isApple$
obj.onValChanged(key: "apple" | "isApple", listener)
, equals to calling obj[`_${key}$`].reaction
Manage life-cycles of a list of Vals (e.g. auto cleanup).
import { Val, ValManager } from "value-enhancer";
const valManager = new ValManager();
const val1 = valManager.attach(new Val("12345"));
const val2 = valManager.attach(new Val(""));
valManager.destroy(); // val1.destroy() and val2.destroy() are called
Combined with withValueEnhancer
or withReadonlyValueEnhancer
:
import type { ValEnhancedResult } from "value-enhancer";
import { Val, withValueEnhancer, ValManager } from "value-enhancer";
class Obj {
constructor() {
this.valManager = new ValManager();
const apple$ = new Val("apple");
const banana$ = new Val("banana");
withValueEnhancer(
this,
{
apple: apple$,
banana: banana$,
},
this.valManager
);
}
destroy() {
this.valManager.destroy();
}
}
And valManager
may keep private with side-effect-manager
:
import type { ValEnhancedResult } from "value-enhancer";
import { Val, withValueEnhancer, ValManager } from "value-enhancer";
import { SideEffectManager } from "side-effect-manager";
class Obj {
constructor() {
this.sideEffect = new SideEffectManager();
const valManager = new ValManager();
this.sideEffect.addDisposer(() => valManager.destroy());
const apple$ = new Val("apple");
const banana$ = new Val("banana");
withValueEnhancer(
this,
{
apple: apple$,
banana: banana$,
},
valManager
);
}
destroy() {
this.sideEffect.flushAll();
}
}
FAQs
Enhance value with plain and explicit reactive wrapper. Think of it as hook-style signals.
We found that value-enhancer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.